# -*- Makefile -*-
#
# $Id$
#
# makedroid: build Android application for old scool
#
# (c)opyleft 2011 Vsevolod S. Balashov <vsevolod@balashov.name>
# distributed under terms of GNU LGPL v3
#
# just symlink me as Makefile into your Android project
# or (and it`s prefered) use `mkapk` tool from this project

# >>> XMLStarlet (http://xmlstar.sf.net/) required

## .SUFFIXES: .apk .ap_ .dex .jar .class .xml .aidl .java .scala

## macros

find.fun = $(shell [ -d $(1) ] && find $(1) -name $(2))
sed.fun = $(shell echo -n $(1) | sed $(2))
getxmlattr.fun = $(shell xml sel -t -v $(1) < $(2))

## project dirs

source.dir = src
gen.dir = gen
resource.dir = res
assets.dir = assets

jar.libs.dir = libs
native.libs.dir = libs

out.dir = bin
out.classes.dir = ${out.dir}/classes

## project files

manifest.xml = AndroidManifest.xml
strings.xml = ${resource.dir}/values/strings.xml

## project metadata

project.name = $(call getxmlattr.fun, "/resources/string[@name='app_name']", ${strings.xml})
ifeq ($(project.name), )
project.name = $(shell basename `pwd`)
endif

project.package = $(call getxmlattr.fun, "/manifest/@package", ${manifest.xml})

## variables & overrides

sdk.dir = $(mkapk_sdk_dir)

ifeq (proguard.cfg, $(wildcard proguard.cfg))
proguard.cfg = proguard.cfg
else
proguard.cfg = $(mkapk_proguard_cfg)
endif

ifeq (local.properties, $(wildcard local.properties))
include local.properties     # sdk.dir
endif

ifeq (default.properties, $(wildcard default.properties))
include default.properties   # target
endif

ifeq (build.properties, $(wildcard build.properties))
include build.properties
endif

## android sdk

android.tools.dir = ${sdk.dir}/tools
android.platform = ${sdk.dir}/platforms/${target}
android.platform.tools.dir = ${sdk.dir}/platform-tools
# android.platform.tools.dir = ${android.platform}/tools

## build tools

AAPT = ${android.platform.tools.dir}/aapt
AIDL = ${android.platform.tools.dir}/aidl
DX = ${android.platform.tools.dir}/dx
APKBUILD = ${android.tools.dir}/apkbuilder
ZIPALIGN = ${android.tools.dir}/zipalign
ADB = ${android.platform.tools.dir}/adb
# PROGUARD = proguard
PROGUARD = ${android.tools.dir}/proguard/bin/proguard.sh
JAVAC = javac
# SCALAC = scalac
SCALAC = fsc

## sdk files

android.jar = ${android.platform}/android.jar
framework.aidl = ${android.platform}/framework.aidl

## build flags

JAVAC_FLAGS = -d ${out.classes.dir}  -sourcepath '${source.path}' -classpath '${class.path}' \
 -bootclasspath ${android.jar} -encoding UTF-8
JAVAC_TARGET = -g -target 1.5 -source 1.5

## sources

resources = $(call find.fun, ${resource.dir}, "*")
assets = $(call find.fun, ${assets.dir}, "*")

R.sources = $(call find.fun, ${res.dir}, "*.xml")
R.java = ${gen.dir}/$(call sed.fun, ${project.package}, 's|\.|\/|g')/R.java

aidl.sources = $(call find.fun, ${source.dir}, "*.aidl")
aidl.java = $(aidl.sources:${source.dir}/%.aidl=${gen.dir}/%.java)

gen.java = ${R.java} ${aidl.java}
gen.classes = $(gen.java:${gen.dir}/%.java=${out.classes.dir}/%.class)

java.sources = $(call find.fun, ${source.dir}, "*.java")
java.classes = $(java.sources:${source.dir}/%.java=${out.classes.dir}/%.class)

scala.sources = $(call find.fun, ${source.dir}, "*.scala")
scala.classes = $(scala.sources:${source.dir}/%.scala=${out.classes.dir}/%.class)

ifeq (${scala.sources}, )
SCALAC := \# $(SCALAC)
endif

classes = ${gen.classes} ${java.classes} ${scala.classes}

## jars & classpath

classes.dex = ${out.dir}/classes.dex
classes.min.jar = ${out.dir}/classes.min.jar

jar.libs = $(wildcard ${jar.libs.dir}/*.jar)
jar.path = $(call sed.fun, ${jar.libs}, 's|\s|:|g')

class.path = ${out.classes.dir}:${jar.path}
source.path = ${source.dir}:${gen.dir}

## debug files

project.resource.debug = ${out.dir}/${project.name}-debug.ap_

project.debug.unaligned = ${out.dir}/${project.name}-debug-unaligned.apk
project.debug = ${out.dir}/${project.name}-debug.apk

## release files

# TODO

## rules

all: debug

clean:
	rm -rf ${out.dir} ${gen.dir}

uninstall:
	$(ADB) uninstall ${project.package}

install: debug
	$(ADB) install -r ${project.debug}

debug: -dirs ${project.debug}

# TODO release:

compile: -dirs ${gen.java}
	$(JAVAC) $(JAVAC_FLAGS) $(JAVAC_TARGET) ${gen.java} ${java.sources}
	$(SCALAC) $(JAVAC_FLAGS) ${scala.sources}

-dirs:
	@mkdir -p ${resource.dir} ${assets.dir} ${jar.libs.dir} ${out.dir} ${gen.dir} ${out.classes.dir}

${project.debug}: ${project.debug.unaligned}
	$(ZIPALIGN) -f 4 $< $@

${project.debug.unaligned}: ${project.resource.debug} ${classes.dex}
	$(APKBUILD) $@ -z ${project.resource.debug} -f ${classes.dex} -d

${project.resource.debug}: ${manifest.xml} ${resources} ${assets}
	$(AAPT) p -f -M ${manifest.xml} -S ${resource.dir} -A ${assets.dir} -I ${android.jar} --debug-mode -F $@

${classes.dex}: ${classes.min.jar}
	$(DX) --dex --output=$@ $<

${classes.min.jar}: ${gen.java} ${classes} ${jar.libs} ${proguard.cfg}
	$(PROGUARD) \
	  -injars '${jar.libs.dir}(!META-INF/*,!*)' \
	  -injars ${out.classes.dir} \
	  -outjars $@ \
	  -libraryjars ${android.jar} \
	  @${proguard.cfg}

${R.java}: ${manifest.xml} ${R.sources}
	$(AAPT) p -f -m -M ${manifest.xml} -S ${resource.dir} -I ${android.jar} -J ${gen.dir}

${gen.dir}/%.java: ${source.dir}/%.aidl
	$(AIDL) -p${framework.aidl} -o${gen.dir} -I${source.dir} $<

${out.classes.dir}/%.class: ${gen.dir}/%.java
	$(JAVAC) $(JAVAC_FLAGS) $(JAVAC_TARGET) $<

${out.classes.dir}/%.class: ${source.dir}/%.java
	$(JAVAC) $(JAVAC_FLAGS) $(JAVAC_TARGET) $<

${out.classes.dir}/%.class: ${source.dir}/%.scala
	$(SCALAC) $(JAVAC_FLAGS) $<
